package com.tcp2.handler;

/**
 * Author: 杨俊辉
 * Time: 2014-09-22 17:34
 * Copyright (C) 2014 Xiamen Yaxon Networks CO.,LTD.
 */

import com.tcp2.msg.rpc.*;
import com.tcp2.net.MasterLink;
import com.tcp2.net.MasterLinkHandler;
import com.tcp2.net.PlatformMap;
import com.tcp2.net.SlaveLink;
import com.tcp2.server.ProtoMsg;
import com.tcp2.util.DeferredResultUtil;
import com.tcp2.util.ProtoUtil;
import com.yaxon.vndp.common.util.CodecUtils;
import com.yaxon.vndp.dms.DmsContext;
import com.yaxon.vndp.dms.Message;
import com.yaxon.vndp.dms.MessageHandler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.ConcurrentMap;
import static com.tcp2.server.ProtoConstants.*;
/**
 * 平台间信息交互处理类
 */
@Service
public class PlatformInfoExchangeHandler extends BaseMsgHandler implements MessageHandler {

    protected static Logger logger = LoggerFactory.getLogger(PlatformInfoExchangeHandler.class);


    @Autowired
    private PlatformCacheServcie platformCacheServcie;

    @Autowired
    private MasterLink masterLink;

    @Override
    public void handle(ProtoMsg msg) {

        logger.info("-> 收到主链路，平台间信息交互，消息id：0x{}，下级平台接入码：{}", CodecUtils.shortToHex((short) msg.msgId), msg.gnssCenterId);
        ByteBuf data = msg.msgData;
        int dataType = data.readUnsignedShort(); //数据类型
        int dataLen = data.readInt();//后续数据长度

        if (dataLen != data.readableBytes()) {
            logger.warn("(UP_PLATFORM):数据长度不一致");
            return;
        }
        switch (dataType) {
            case UP_PLATFORM_MSG_POST_QUERY_ACK:
                doUpPlatformMsgPostQueryAck(data, dataType, msg.gnssCenterId);
                break;
            case UP_PLATFORM_MSG_INFO_ACK:
                doUpPlatformMsgInfoAck(data, dataType, msg.gnssCenterId);
                break;
            default:
                throw new RuntimeException("未知子业务类型：0x" + CodecUtils.shortToHex((short) dataType));

        }
    }

    /**
     * RPC消息处理器
     */
    @Override
    public void onReceive(DmsContext ctx, Message req) {
        if (req instanceof Dn_9301) {//平台查岗请求
            doDownPlatformMsgInfoReq(ctx, (Dn_9301) req);
        }else if (req instanceof Dn_9302) {//下发平台报文
            doDownPlatformMsgPostQueryReq(ctx, (Dn_9302) req);
        }else if(req instanceof Dn_ActiveOrFrozenPlatForm)
        {
            doActiveOrFrozenPlatFormReq(ctx, (Dn_ActiveOrFrozenPlatForm) req);
        }
        else {
            throw new RuntimeException("未知的请求消息类型: " + req.getClass().getName());
        }
    }

    private void doUpPlatformMsgPostQueryAck(ByteBuf data, int dataType, int gnssCenterId) {
        logger.info("-> 收到主链路，平台查岗应答，子业务类型 ：0x{}", CodecUtils.shortToHex((short) dataType));
        logger.info("字节数{}，16进制:{}", data.readableBytes(), ByteBufUtil.hexDump(data).replaceAll("\\w{2}(?!$)", "$0 ").toUpperCase());
        //详见补充协议

        byte objType = data.readByte();
        String objId = ProtoUtil.readOctetString(data, 12);
        Long infoId = (long) data.readInt();
        String infoContent = ProtoUtil.readU32String(data);
        try {

        } catch (Exception e) {
            logger.warn("往数据库更新平台查岗记录异常", e);
        }

    }

    private void doUpPlatformMsgInfoAck(ByteBuf data, int dataType, int gnssCenterId) {
        logger.info("-> 收到主链路，下发平台间报文应答，子业务类型 ：0x{}", CodecUtils.shortToHex((short) dataType));
        logger.info("字节数{}，16进制:{}", data.readableBytes(), ByteBufUtil.hexDump(data).replaceAll("\\w{2}(?!$)", "$0 ").toUpperCase());
        Up_1302 res = new Up_1302();
        try {
            res.setInfoId(data.readInt());
            DeferredResultUtil.getInstance().setResult("1302:" + res.getInfoId(), res);
        } catch (Exception e) {
            logger.warn("下发平台间报文应答失败", e);
            res.setRc(BaseRes.RC_FAIL);
        }
    }

    private void doDownPlatformMsgInfoReq(final DmsContext ctx, Dn_9301 req) {
        logger.info("<- 发送从链路，发送平台查岗请求，对象id ：{}", req.getObjId());
        SimpleRes res = new SimpleRes();
        try {
            Validate.notNull(req.getObjType(), "对象类型不能为空");
            Validate.notNull(req.getObjId(), "对象id不能为空");
            Validate.notNull(req.getInfoContent(), "消息内容不能为空");
        } catch (Exception e) {
            res.setRc(BaseRes.RC_FAIL);
            res.setErrMsg("请求参数不合法");
            ctx.reply(res);
            return;
        }




        try {
            ProtoMsg out = new ProtoMsg();
            out.msgId = DOWN_PLATFORM_MSG;
            ByteBuf data = Unpooled.buffer(0);
            out.msgData = data;

            data.writeShort(DOWN_PLATFORM_MSG_POST_QUERY_REQ);
            int startIndex = data.writerIndex();
            data.writeInt(0);//数据长度
            data.writeByte(req.getObjType());
            ProtoUtil.writeOctetString(data, req.getObjId(), 12);

            ProtoUtil.writeU32String(data, req.getInfoContent());

            int dataLen = data.writerIndex() - startIndex - 4;
            data.setInt(startIndex, dataLen); //写入实际的数据长度

            ConcurrentMap<Integer, SlaveLink> gov2platMap = PlatformMap.getGov2platMap();
            SlaveLink slaveLink = gov2platMap.get(Integer.valueOf(req.getObjId()));
            if (slaveLink != null) {
                ByteBuf msgData=data.copy();
                slaveLink.sendMessage(out);
                try{
                    //保存记录
                    String msgTxt="平台间查岗请求:对应流水号：*,对应消息ID:0x9301,查岗对象类型:"+req.getObjType()
                            +",查岗对象ID:"+req.getObjId()+",数据内容:"+req.getInfoContent();
                    //messageDispatcher.saveSlaveLinkExcLog("0x9301",msgTxt,msgData,(byte)1);
                }catch (Exception e) {
                    logger.warn("从链路数据交互记录添加异常", e);
                }
            } else {
                throw new Exception("未建立从链路,接入码:" + req.getObjId());
            }

            res.setRc(BaseRes.RC_OK);
            ctx.reply(res);
        } catch (Exception e) {
            logger.warn("发送平台查岗请求失败", e);
            res.setRc(BaseRes.RC_FAIL);
            ctx.reply(res);
            return;
        }
    }

    private void doDownPlatformMsgPostQueryReq(final DmsContext ctx, Dn_9302 req) {
        logger.info("<- 发送从链路，下发平台间报文请求，对象id ：{}", req.getObjId());
        Up_1302 res = new Up_1302();
        try {
            Validate.notNull(req.getObjType(), "对象类型不能为空");
            Validate.notNull(req.getObjId(), "对象id不能为空");
            Validate.notNull(req.getInfoId(), "消息id不能为空");
            Validate.notNull(req.getInfoContent(), "消息内容不能为空");
        } catch (Exception e) {
            res.setRc(BaseRes.RC_FAIL);
            res.setErrMsg("请求参数不合法");
            ctx.reply(res);
            return;
        }

        String fno = "1302:" + req.getInfoId();
        putFuture(fno, ctx, res);

        try {
            ProtoMsg out = new ProtoMsg();
            out.msgId = DOWN_PLATFORM_MSG;
            ByteBuf data = Unpooled.buffer(0);
            out.msgData = data;

            data.writeShort(DOWN_PLATFORM_MSG_INFO_REQ);
            int startIndex = data.writerIndex();
            data.writeInt(0);//数据长度
            data.writeByte(req.getObjType());
            ProtoUtil.writeOctetString(data, req.getObjId(), 12);
            data.writeInt(req.getInfoId());
            ProtoUtil.writeU32String(data, req.getInfoContent());
            int dataLen = data.writerIndex() - startIndex - 4;
            data.setInt(startIndex, dataLen); //写入实际的数据长度
            ConcurrentMap<Integer, SlaveLink> gov2platMap = PlatformMap.getGov2platMap();
            SlaveLink slaveLink = gov2platMap.get(Integer.valueOf(req.getObjId()));
            if (slaveLink != null) {
                ByteBuf msgData=data.copy();
                slaveLink.sendMessage(out);
                try{
                    //保存记录
                    String msgTxt="下发平台间报文请求:对应流水号：*,对应消息ID:0x9302,下发报文对象类型:"+req.getObjType()
                            +",下发报文对象ID:"+req.getObjId()+",数据内容:"+req.getInfoContent();
                    //messageDispatcher.saveSlaveLinkExcLog("0x9302",msgTxt,msgData,(byte)1);
                }catch (Exception e) {
                    logger.warn("从链路数据交互记录添加异常", e);
                }
            } else {
                throw new Exception("未建立从链路，接入码:" + req.getObjId());
            }
        } catch (Exception e) {
            logger.warn("下发平台间报文请求失败", e);
            DeferredResultUtil.getInstance().setExcepion(fno, e);
        }
    }

    private void doActiveOrFrozenPlatFormReq(final DmsContext ctx, Dn_ActiveOrFrozenPlatForm req)
    {
        Up_ActiveOrFrozenPlatForm res=new Up_ActiveOrFrozenPlatForm();
        Byte accessStatu=0;
        try {
            Validate.notNull(req.getAccessCode(), "对象平台接入码不能为空");
            Validate.notNull(req.getStatu(), "对象 状态不能为空");

        } catch (Exception e) {
            logger.info("请求参数不合法");
            return;
        }
        try {

            ConcurrentMap<Integer, SlaveLink> gov2platMap = PlatformMap.getGov2platMap();
            SlaveLink slaveLink = gov2platMap.get(req.getAccessCode());
            ConcurrentMap<Integer, MasterLinkHandler> plat2govMap=PlatformMap.getPlat2govMap();
            MasterLinkHandler masterLinkHandler=plat2govMap.get(req.getAccessCode());
          //  platformCacheServcie.removePlatformById(req.getAccessCode());//移除缓存
           if(req.getStatu()==0) { //做冻结操作时
               logger.info("冻结下级平台，将断开下级平台...");
               if (slaveLink != null) {
                   slaveLink.stop();
                   gov2platMap.remove(req.getAccessCode());
                   accessStatu=0;
               }
               if (masterLinkHandler != null) {
                   masterLink.stop();
                   plat2govMap.remove(req.getAccessCode());
                   masterLink.savePlatformLinkLog(req.getAccessCode(), req.getStatu(), (byte) 2);
                   accessStatu=0;
               }

           }
           if(req.getStatu()==1)
           {
               logger.info("激活下级平台，将连接下级平台...");
               if(masterLinkHandler==null)
               {
                   masterLink.savePlatformLinkLog(req.getAccessCode(), req.getStatu(), (byte) 1);
                   masterLink.start();
                   accessStatu=1;
               }

           }
        }
            catch(Exception e){
                if(req.getStatu()==0){
                logger.warn("冻结主从链路异常", e);
                }else{
                    logger.warn("激活主从链路异常", e);
                }
            }
        res.setAccessStatu(accessStatu);
        res.setAccessCode(req.getAccessCode());
        ctx.reply(res);
        }


}
